package com.gitee.faster.webdav.logger;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.lang.ansi.AnsiColor;
import cn.hutool.core.lang.ansi.AnsiEncoder;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.gitee.faster.webdav.common.constant.Constants;
import org.slf4j.event.Level;

import java.util.Date;
import java.util.Optional;
import java.util.function.Function;

import static java.lang.System.out;

/**
 * @author hongda.li
 */
public class ConsoleProcessor implements LoggerProcessor {
    /**
     * 线程名称最大长度
     */
    private static final int MAX_THREAD_NAME_LENGTH = 15;

    /**
     * 控制台打印时间的颜色
     */
    private static final AnsiColor COLOR_TIME = AnsiColor.WHITE;

    /**
     * 控制台打印类名（日志名称）的颜色
     */
    private static final AnsiColor COLOR_CLASSNAME = AnsiColor.MAGENTA;

    /**
     * 日志级别与日志对应的颜色映射关系
     */
    private static final Function<Level, AnsiColor> COLOR_MAPPING = level -> switch (level) {
        case INFO -> AnsiColor.BRIGHT_CYAN;
        case ERROR -> AnsiColor.BRIGHT_RED;
        case TRACE -> AnsiColor.BRIGHT_BLUE;
        case WARN -> AnsiColor.BRIGHT_YELLOW;
        default -> AnsiColor.WHITE;
    };

    @Override
    public void process(String name, Level level, String message, Throwable throwable, Object[] args) {
        // 根据日志级别获取对应的颜色定义
        AnsiColor color = COLOR_MAPPING.apply(level);

        // 根据颜色定义生成特殊编码的模板
        final String template = AnsiEncoder.encode(COLOR_TIME, "%s", color, " [%-5s] [%-15s]%s", COLOR_CLASSNAME, "%-45s: ", color, "%s%n");

        // 格式化特殊编码模板并输出到控制台
        out.format(template,
                this.formatTime(),
                level.name(),
                this.currentThreadName(),
                Constants.DASH_SYMBOL,
                ClassUtil.getShortClassName(name),
                this.formatMessage(message, args));

        // 若异常存在则打印
        Optional.ofNullable(throwable).ifPresent(item -> item.printStackTrace(out));
    }

    /**
     * 生成 yyyy-MM-dd HH:mm:ss.SSS 格式的时间
     *
     * @return 当前时间字符串
     */
    protected String formatTime() {
        return DatePattern.NORM_DATETIME_MS_FORMAT.format(new Date());
    }

    /**
     * 格式化消息模板，将其中的 {} 替换为对应的参数值
     *
     * @param message 原始消息模板
     * @param args    消息参数
     * @return 格式化后的字符串
     */
    protected String formatMessage(String message, Object[] args) {
        return CharSequenceUtil.format(message, args);
    }

    /**
     * 获取当前的线程名称，并将长度截断至 15 个字符以内
     *
     * @return 线程名称
     */
    protected String currentThreadName() {
        String name = Thread.currentThread().getName();
        return name.length() > MAX_THREAD_NAME_LENGTH ? StrUtil.subSufByLength(name, MAX_THREAD_NAME_LENGTH) : name;
    }
}
